#include "snowboy/snowboy-detect-c-wrapper.h"
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include "record.h"
#include "stt.h"
#include "tts.h"
#include "jrsc.h"
#include "config.h"
#include "http.h"
char *app_id = "62b84ef5-5daf-491d-97a8-5966fb4deb34";
char *conv_id = NULL;

// led控制
void led_control(char *led, char *status)
{
    char file_path[50] = "/sys/class/leds/";
    sprintf(file_path, "%s%s%s", file_path, led, "/brightness");
    FILE *fp = fopen(file_path, "w");
    if (fp == NULL)
    {
        perror("打开LED设备文件失败");
        return;
    }
    fprintf(fp, status);
    fflush(fp);
    // 关闭LED设备文件
    fclose(fp);
}
// 创建会话
char *create_conversation(char *authtoken)
{
    char *url = "https://qianfan.baidubce.com/v2/app/conversation";

    // 拼接Authorization字段
    char *auth;
    asprintf(&auth, "Authorization: Bearer %s", authtoken);

    // 添加请求头部字段
    struct curl_slist *headers = NULL;
    headers = curl_slist_append(headers, "Content-Type: application/json;charset=utf-8");
    headers = curl_slist_append(headers, auth);

    // 准备请求正文
    cJSON *obj = cJSON_CreateObject();
    cJSON_AddStringToObject(obj, "app_id", app_id);
    // 将JSON对象转换为JSON字符串
    char *json = cJSON_Print(obj);

    // 发送请求
    size_t size = strlen(json);
    char *response = http_post(url, headers, json, &size);
    cJSON_Delete(obj);
    free(json);
    free(auth);
    curl_slist_free_all(headers);

    if (!response)
    {
        return NULL;
    }

    obj = cJSON_ParseWithLength(response, size);
    free(response);

    if (!obj)
    {
        fprintf(stderr, "解析 JSON 失败: [%s]\n", cJSON_GetErrorPtr());
        return NULL;
    }

    cJSON *conversation_id = cJSON_GetObjectItem(obj, "conversation_id");
    if (!conversation_id)
    {
        fprintf(stderr, "conversation_id 字段不存在\n");
        cJSON_Delete(obj);
        return NULL;
    }

    char *retval = strdup(conversation_id->valuestring);

    cJSON_Delete(obj);

    return retval;
}

// 调用对话API
// authtoken: 平台密钥
// conv_id: 会话ID
// query: 用户输入的文本
// 返回值: 对话结果
char *chat(char *authtoken, char *conv_id, char *query)
{
    char *url = "https://qianfan.baidubce.com/v2/app/conversation/runs";

    // 拼接Authorization字段
    char *auth;
    asprintf(&auth, "Authorization: Bearer %s", authtoken);

    // 设置请求头部字段
    struct curl_slist *headers = NULL;
    headers = curl_slist_append(headers, "Content-Type: application/json;charset=utf-8");
    headers = curl_slist_append(headers, auth);

    // 准备请求正文
    cJSON *obj = cJSON_CreateObject();
    cJSON_AddStringToObject(obj, "app_id", app_id);
    cJSON_AddStringToObject(obj, "conversation_id", conv_id);
    cJSON_AddStringToObject(obj, "query", query);
    cJSON_AddBoolToObject(obj, "stream", false);
    // 将JSON对象转换为JSON字符串
    char *json = cJSON_Print(obj);

    // 发送请求
    size_t size = strlen(json);
    char *response = http_post(url, headers, json, &size);
    cJSON_Delete(obj);
    free(json);
    curl_slist_free_all(headers);
    free(auth);

    if (!response)
    {
        return NULL;
    }

    obj = cJSON_ParseWithLength(response, size);
    free(response);

    if (!obj)
    {
        fprintf(stderr, "解析 JSON 失败: [%s]\n", cJSON_GetErrorPtr());
        return NULL;
    }

    cJSON *answer = cJSON_GetObjectItem(obj, "answer");
    if (!answer)
    {
        fprintf(stderr, "answer 字段不存在\n");
        puts(cJSON_Print(obj));
        cJSON_Delete(obj);
        return NULL;
    }

    char *retval = strdup(answer->valuestring);

    cJSON_Delete(obj);

    return retval;
}


int main()
{
    // 创建snowboy检测器
    SnowboyDetect *detector = SnowboyDetectConstructor("common.res", "model.pmdl");
    if (!detector)
    {
        return EXIT_FAILURE;
    }

    // 获取检测器支持的音频数据参数
    // 采样深度
    int bits = SnowboyDetectBitsPerSample(detector);
    // 声道数量
    int channels = SnowboyDetectNumChannels(detector);
    // 采样频率
    int rate = SnowboyDetectSampleRate(detector);

    printf("采样深度: %d\n", bits);
    printf("声道数量: %d\n", channels);
    printf("采样频率: %d\n", rate);

    // 打开音频采集设备
    snd_pcm_uframes_t period = 999;
    snd_pcm_t *capture = record_open("hw:0,0", SND_PCM_FORMAT_S16_LE, channels, rate, &period);
    if (!capture)
    {
        return EXIT_FAILURE;
    }

    char *buffer = malloc(snd_pcm_frames_to_bytes(capture, period)); // 分配缓冲区
    if (!buffer)
    {
        perror("malloc");
        record_close(capture);
        SnowboyDetectDestructor(detector);
        return EXIT_FAILURE;
    }

    int recording = 0;
    // 检测到连续的静音次数
    int silence = 0;
    // 内存文件
    FILE *memstream = NULL;
    char *audio = NULL;
    size_t audio_size = 0;

    while (1)
    {
        snd_pcm_sframes_t frames = snd_pcm_readi(capture, buffer, period); // 从PCM设备读取数据
        if (frames < 0)
        {
            // fprintf(stderr, "Error from read: %s\n", snd_strerror(frames));
            snd_pcm_recover(capture, frames, 0);
            continue;
        }

        //-2: 静音
        //-1: 检测出错
        // 0: 有声音，但不是唤醒词
        //>0: 检测到唤醒词
        int status = SnowboyDetectRunDetection(detector, (int16_t *)buffer, snd_pcm_frames_to_bytes(capture, frames) / sizeof(int16_t), 0);
        if (status > 0)
        {
            printf("在呢在呢，请说👂\n\n");
            // 录音时led3亮，其他灭
            led_control("led3", "1");
            led_control("led1", "1");
            led_control("led2", "1");
            recording = 1;
            // 打开内存文件
            memstream = open_memstream(&audio, &audio_size);
            if (!memstream)
            {
                perror("open_memstream");
                continue;
            }
        }
        if (status == -2)
        {
            // 静音时led1亮
            led_control("led1", "1");
            led_control("led2", "0");
            led_control("led3", "0");
        }
        if (status == 0)
        {
            // 有声音，不是唤醒词led2亮，其他灯灭
            led_control("led2", "1");
            led_control("led1", "0");
            led_control("led3", "0");
        }
        if (recording)
        {
            if (status == -2)
            {
                silence++;
            }

            if (status == 0)
            {
                silence = 0;
            }

            if (silence > 48)
            {
                printf("好的，正在处理请稍候！\n");
                // led_control("led3", "0");
                // led_control("led1", "0");
                // led_control("led2", "0");
                recording = 0;
                silence = 0;
                if (memstream)
                {
                    fclose(memstream);
                    memstream = NULL;
                }

                if (audio_size)
                {
                    // 暂停录音
                    snd_pcm_drop(capture);
                    // 识别语音
                    char *text = speech_to_text(audio, audio_size);
                    if (text)
                    {
                        printf(">%s\n\n", text);
                    }

                    // 读取配置文件中的平台密钥
                    cJSON *config = read_config("config.json");
                    if (!config)
                    {
                        return EXIT_FAILURE;
                    }

                    cJSON *authtoken = cJSON_GetObjectItem(config, "authtoken");
                    if (!authtoken)
                    {
                        fprintf(stderr, "配置文件错误: 找不到 'authtoken' 字段\n");
                        cJSON_Delete(config);
                        return EXIT_FAILURE;
                    }
                    // printf("%s\n", authtoken->valuestring);
                    // 创建会话
                    if (!conv_id)
                    {
                        conv_id = create_conversation(authtoken->valuestring);
                    }
                    // printf("conv_id: %s\n", conv_id);
                    char *answer = chat(authtoken->valuestring, conv_id, text);
                    printf("< %s\n", answer);

                    text_to_speech(answer);

                    // 恢复录音
                    snd_pcm_prepare(capture);
                }
            }

            if (memstream)
            {
                fwrite(buffer, 1, snd_pcm_frames_to_bytes(capture, frames), memstream);
            }
        }
    }

    free(buffer);
    record_close(capture);
    SnowboyDetectDestructor(detector);

    return EXIT_SUCCESS;
}